﻿using lucere.analysis.query;
using lucere.analysis.query.filter;
using lucere.service.search.collect;

namespace lucere.service.search
{
	//TODO: define BooleanQuery.TooManyClauses
	///<summary>
	/// An abstract base class for search implementations. Implements the main search
	/// methods.
	/// Note that you can only access hits from a Searcher as long as it is not yet
	/// closed, otherwise an IOException will be thrown.
	///</summary>
	public interface ISearcher : ISearchable
	{
		///<summary>
		/// Search implementation with arbitrary sorting.  Finds
		/// the top <code>n</code> hits for <code>query</code>, applying
		/// <code>filter</code> if non-null, and sorting the hits by the criteria in
		/// <code>sort</code>.
		/// 
		/// NOTE: this does not compute scores by default; use
		/// <see cref="IIndexSearcher.DefaultFieldSortScoring"></see> to
		/// enable scoring.
		///
		///</summary>
		/// <param name="query"></param>
		/// <param name="filter"></param>
		/// <param name="n"></param>
		/// <param name="sort"></param>
		/// <returns></returns>
		///<exception cref="BooleanQuery.TooManyClauses"></exception>
		ITopFieldDocs Search(IQuery query, IFilter filter, int n, ISort sort);

		///<summary>
		/// Lower-level search API.
		/// <p><see cref="ICollector.Collect(int)"></see> is called for every matching document. </p>
		/// Applications should only use this if they need <i>all</i> of the
		/// matching documents.  The high-level search API (<see cref="ISearcher.Search(IQuery, int)"></see>) is usually more efficient, as it skips
		/// non-high-scoring hits.
		/// <p>Note: The <code>score</code> passed to this method is a raw score.
		/// In other words, the score will not necessarily be a float whose value is
		/// between 0 and 1.
		/// </p>
		///</summary>
		///<exception cref="BooleanQuery.TooManyClauses"></exception>
		void Search(IQuery query, ICollector results);

		///<summary>
		/// Lower-level search API.
		/// <p><see cref="ICollector.Collect(int)"></see> is called for every matching
		/// document.
		/// <br/>Collector-based access to remote indexes is discouraged.
		///
		/// </p>p>Applications should only use this if they need <i>all</i> of the
		/// matching documents.  The high-level search API (<see cref="ISearcher.Search(IQuery, IFilter, int)"></see>) is usually more efficient, as it skips
		/// non-high-scoring hits.
		/// </summary>
		/// <param name="query">to match documents</param>
		/// <param name="filter">if non-null, used to permit documents to be collected.</param>
		/// <param name="results">to receive hits</param>
		///<exception cref="BooleanQuery.TooManyClauses"></exception>
		void Search(IQuery query, IFilter filter, ICollector results);

		///<summary>
		/// Finds the top <code>n</code>
		/// hits for <code>query</code>, applying <code>filter</code> if non-null.
		/// </summary>
		///<exception cref="BooleanQuery.TooManyClauses"></exception>
		ITopDocs Search(IQuery query, IFilter filter, int n);

		///<summary>
		/// Finds the top <code>n</code>
		/// hits for <code>query</code>.
		///</summary>
		///<exception cref="BooleanQuery.TooManyClauses"></exception>
		ITopDocs Search(IQuery query, int n);

		///<summary>
		///Returns an Explanation that describes how <code>doc</code> scored against
		/// <code>query</code>.
		/// 
		/// This is intended to be used in developing Similarity implementations,
		/// and, for good performance, should not be displayed with every hit.
		/// Computing an explanation is as expensive as executing the query over the
		/// entire index.
		///</summary>  
		IExplanation Explain(IQuery query, int doc);

		///<summary>
		///Expert: Set the Similarity implementation used by this Searcher.
		/// <see cref="ISimilarity.Default(ISimilarity)"></see>
		///</summary>
		ISimilarity Similarity { get; set; }
	}
}